---
redirect_from:
  - /real-time-data-fetch
---

# Real-Time data fetch

Most of databases supported by Cube are retroactive. It means Cube should
continuously poll for changes rather than receive updates as a subscribed
listener. Cube provides a convenient way to create such polling database
subscriptions on your behalf.

## Web Sockets

To provide the best real-time experience it's recommended to use Web Sockets
transport instead of the default http long polling. Web sockets on backend can
be enabled using `CUBEJS_WEB_SOCKETS` environment variable:

**.env:**

```dotenv
CUBEJS_WEB_SOCKETS=true
```

Clients can be switched to Web Sockets by passing `WebSocketTransport` to
`CubeApi` constructor:

```javascript
import cube from "@cubejs-client/core";
import WebSocketTransport from "@cubejs-client/ws-transport";

const cubeApi = cube({
  transport: new WebSocketTransport({
    authorization: CUBE_TOKEN,
    apiUrl: "ws://localhost:4000/",
  }),
});
```

## Client Subscriptions

Multiple APIs are provided to support data subscription scenarios.

### Vanilla JavaScript

```javascript
import cube from "@cubejs-client/core";
import WebSocketTransport from "@cubejs-client/ws-transport";

const cubeApi = cube({
  transport: new WebSocketTransport({
    authorization: CUBE_TOKEN,
    apiUrl: "ws://localhost:4000/",
  }),
});

// Create a subscription
const subscription = cubeApi.subscribe(
  {
    measures: ["logs.count"],
    timeDimensions: [
      {
        dimension: "logs.time",
        granularity: "hour",
        dateRange: "last 1440 minutes",
      },
    ],
  },
  options,
  (error, resultSet) => {
    if (!error) {
      // handle the update
    }
  }
);

// Later on, unsubscribe from subscription
subscription.unsubscribe();
```

### React hooks

```javascript
import { useCubeQuery } from "@cubejs-client/react";

const Chart = ({ query }) => {
  const { resultSet, error, isLoading } = useCubeQuery(query, {
    // The component will automatically unsubscribe when unmounted
    subscribe: true,
  });

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <pre>{error.toString()}</pre>;
  }

  if (!resultSet) {
    return null;
  }

  return <LineChart resultSet={resultSet} />;
};
```

## Refresh Rate

As in the case of a regular data fetch, real-time data fetch obeys
[`refresh_key` refresh rules](/product/caching#refresh-keys). In order to
provide a desired refresh rate, `refresh_key` should reflect the rate of change
of the underlying data set; the querying time should also be much less than the
desired refresh rate. Please use the
[`every`](/reference/data-model/cube#refresh_key) parameter to adjust
the refresh interval.
